package cate.game.rank;

import cate.game.activity.rank.BaseRankActivityHandler;
import cate.game.db.SaveConstants;
import cate.game.db.facade.KvLoader;
import cate.game.db.mongo.kv.KvMongo;
import cate.game.rank.cross.h.ChampionRaceRankLoader;
import cate.game.rank.h.EndlessRankHandler;
import cate.game.framework.ModuleMan;
import cate.game.rank.h.*;
import cate.game.rank.h.adapter.EliteRaceRankHandlerAdapter;
import cate.game.rank.h.adapter.PointRaceRankHandlerAdapter;
import cate.game.rank.history.RankHistorySPO;
import cate.game.rank.history.RankReachHistory;
import cate.game.rank.po.Rank;
import cate.game.role.Role;
import cate.game.rank.h.ForbiddenRankHandlers;
import cate.game.util.IntervalCounter;
import lombok.Getter;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 排行榜模块管理
 */
public class RankManager extends ModuleMan {

    private final Map<Integer, IRankFuncHandler<? extends Rank>> handlers = new HashMap<>();

    private final Map<Integer, BaseRankActivityHandler> rankActivityHandlers = new HashMap<>();

    public final RankTowerHandler tower = new RankTowerHandler();

    public final CampHeroPowerHandlers camps = new CampHeroPowerHandlers();

    public final RankAchievementHandler achievements = new RankAchievementHandler();

    public final RankPowerHandler power = new RankPowerHandler();

    public final RankLevelHandler level = new RankLevelHandler();

    public final ForbiddenRankHandlers forbidden = new ForbiddenRankHandlers();

    public final EndlessRankHandler endless = new EndlessRankHandler();

    @Getter
    private final PointRaceRankHandlerAdapter pointRaceAdapter = new PointRaceRankHandlerAdapter();

    @Getter
    private final EliteRaceRankHandlerAdapter eliteRaceAdapter = new EliteRaceRankHandlerAdapter();

    public final UdgPalaceRankHandler udgPalace = new UdgPalaceRankHandler();

    public final ChampionRaceRankLoader championRace = new ChampionRaceRankLoader();

    public final RankTeamPvpLoader teamPvp = new RankTeamPvpLoader();

    public RankHistorySPO data;

    @Override
    public void initDependent() throws Exception {
        data = new KvLoader<>(game, RankHistorySPO.class, KvMongo.KEY_RANK).getBySrvId();
        data.initialize(game);
        //依赖game.db
        tower.initialize(game);
        achievements.initialize(game);
        power.initialize(game);
        camps.initialize(game);
        forbidden.initialize(game);
        pointRaceAdapter.initialize(game);
        eliteRaceAdapter.initialize(game);
        level.initialize(game);
        endless.initialize(game);
        udgPalace.initialize(game);
        championRace.initialize(game);
        teamPvp.initialize(game);
        //功能预留, 如果排行榜奖励后延，会涉及较多判断, 尽量确定后延再开启
//        checkHistory();
    }

    private void checkHistory() {
        if (!handlers.isEmpty()) {
            for (int rankId : handlers.keySet()) {
                if (rankId == 0 || !game.table.rank.hasReward(rankId)) {
                    continue;
                }
                Rank rank = handlers.get(rankId).getRankOneData(null);
                if (rank != null) {
                    data.record(rankId, rank);
                }
            }
        }
    }

    public void registeHandler(IRankFuncHandler<?> handler) {
        if (handler.getRankId() != 0) {
            handlers.put(handler.getRankId(), handler);
        }
    }

    public void updateRole(Role role) {
        try{
            tower.updateRole(role);
            achievements.updateRole(role);
            power.updateRole(role);
            forbidden.updateRole(role);
            endless.updateRole(role);
            rankActivityHandlers.values().forEach(e -> e.updateRole(role));
            camps.updateRole(role);
        }catch(Exception e){
            log.error("登录时更新角色排行榜信息异常，e=",e);
        }

    }

    @Override
    public synchronized void shutdown() {
        tower.forceSave();
        achievements.forceSave();
        power.forceSave();
        camps.forceSave();
        forbidden.forceSave();
        game.db.kv.save(data);
        level.forceSave();
        endless.forceSave();
        udgPalace.forceSave();
        rankActivityHandlers.values().forEach(RankHandler::forceSave);
    }

    public Map<Integer, RankReachHistory> getRankHistory(int rankId) {
        return data.getRankHistory(rankId);
    }

    public IRankFuncHandler<? extends Rank> getRankHandler(int rankId) {
        IRankFuncHandler<? extends Rank> handler = handlers.get(rankId);
        if(handler != null){
            return handler;
        }
        return rankActivityHandlers.get(rankId);
    }

    public void handleAdmire(String uid, int rankId) {
        if (!StringUtils.hasLength(uid)) {
            return;
        }

        Role role = game.role.getRole(uid);
        if (Objects.nonNull(role)) {
            role.getFarm().rank.beAdmire(rankId);
        }
    }

    private static final AtomicInteger IDX = new AtomicInteger(0);
    private final IntervalCounter saveTrigger = new IntervalCounter(SaveConstants.RANK_SAVE_SECONDS, IDX.getAndIncrement());

    public void tick(){
        if(saveTrigger.trigger()){
            long start = System.currentTimeMillis();
            game.db.kv.save(data);
            log.debug("game rank定时保存完成, cost{} ms", System.currentTimeMillis() - start);
        }
    }

    public boolean existRankHandler(int rankId){
        return handlers.containsKey(rankId);
    }


    public void registerRankActivityHandler(BaseRankActivityHandler handler) {
        if (handler.getRankId() > 0) {
            rankActivityHandlers.put(handler.getRankId(), handler);
        }
    }
}